<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Exception;
use Throwable;

class GenerateThumbnailJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $imageFile;
    protected $sourcePath;
    protected $targetPath;
    protected $size;

    /**
     * 任务超时时间（秒）
     */
    public $timeout = 3600;

    /**
     * 任务最大尝试次数
     */
    public $tries = 3;

    /**
     * Create a new job instance.
     */
    public function __construct(string $imageFile, string $sourcePath = 'images', string $targetPath = 'images_small', int $size = 100)
    {
        $this->imageFile = $imageFile;
        $this->sourcePath = $sourcePath;
        $this->targetPath = $targetPath;
        $this->size = $size;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        try {
            Log::info("开始处理缩略图任务", [
                'image_file' => $this->imageFile,
                'target_path' => $this->targetPath,
                'size' => $this->size
            ]);

            $disk = Storage::disk('public');
            
            // 构建目标文件路径，保持目录结构
            $targetFile = str_replace($this->sourcePath, $this->targetPath, $this->imageFile);
            
            // 检查目标文件是否已存在
            if ($disk->exists($targetFile)) {
                Log::info("缩略图已存在，跳过任务: {$targetFile}");
                return;
            }
            
            // 确保目标目录存在
            $targetDir = dirname($targetFile);
            if (!$disk->exists($targetDir)) {
                $disk->makeDirectory($targetDir, 0755, true);
            }
            
            // 读取原始图片
            $imagePath = $disk->path($this->imageFile);
            
            if (!file_exists($imagePath)) {
                throw new Exception("原始图片文件不存在: {$this->imageFile}");
            }
            
            // 使用原生 PHP GD 库生成缩略图（更稳定的方案）
            $targetFilePath = $disk->path($targetFile);
            $this->generateThumbnailWithGD($imagePath, $targetFilePath, $this->size);
            
            Log::info("缩略图任务完成", [
                'source_file' => $this->imageFile,
                'target_file' => $targetFile,
                'size' => $this->size
            ]);
            
        } catch (Exception $e) {
            Log::error("缩略图任务失败", [
                'image_file' => $this->imageFile,
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
            
            // 重新抛出异常，让队列系统处理重试
            throw $e;
        }
    }

    /**
     * 使用 GD 库生成缩略图
     */
    private function generateThumbnailWithGD($sourcePath, $targetPath, $size): void
    {
        // 标准化路径
        $sourcePath = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $sourcePath);
        $targetPath = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $targetPath);
        
        // 检查源文件是否存在
        if (!file_exists($sourcePath)) {
            throw new Exception("源图片文件不存在: {$sourcePath}");
        }
        
        // 获取原始图片信息
        $imageInfo = getimagesize($sourcePath);
        if (!$imageInfo) {
            throw new Exception("无法获取图片信息，文件可能损坏: {$sourcePath}");
        }

        $originalWidth = $imageInfo[0];
        $originalHeight = $imageInfo[1];
        $mimeType = $imageInfo['mime'];

        // 根据 MIME 类型创建图片资源
        switch ($mimeType) {
            case 'image/jpeg':
                $sourceImage = imagecreatefromjpeg($sourcePath);
                break;
            case 'image/png':
                $sourceImage = imagecreatefrompng($sourcePath);
                break;
            case 'image/gif':
                $sourceImage = imagecreatefromgif($sourcePath);
                break;
            case 'image/webp':
                if (function_exists('imagecreatefromwebp')) {
                    $sourceImage = imagecreatefromwebp($sourcePath);
                } else {
                    throw new Exception("WebP 格式不支持");
                }
                break;
            default:
                throw new Exception("不支持的图片格式: {$mimeType}");
        }

        if (!$sourceImage) {
            throw new Exception("无法创建图片资源");
        }

        // 创建缩略图画布
        $thumbnail = imagecreatetruecolor($size, $size);
        
        // 根据图片格式设置背景
        if ($mimeType === 'image/png') {
            // PNG格式：透明背景
            imagealphablending($thumbnail, false);
            imagesavealpha($thumbnail, true);
            $transparent = imagecolorallocatealpha($thumbnail, 0, 0, 0, 127);
            imagefill($thumbnail, 0, 0, $transparent);
        } else {
            // JPG等其他格式：白色背景
            $white = imagecolorallocate($thumbnail, 255, 255, 255);
            imagefill($thumbnail, 0, 0, $white);
        }

        // 计算缩放比例（保持宽高比，居中裁剪）
        $scale = max($originalWidth / $size, $originalHeight / $size);
        $newWidth = $originalWidth / $scale;
        $newHeight = $originalHeight / $scale;
        
        $offsetX = ($size - $newWidth) / 2;
        $offsetY = ($size - $newHeight) / 2;

        // 复制并缩放图片
        imagecopyresampled(
            $thumbnail, $sourceImage,
            $offsetX, $offsetY, 0, 0,
            $newWidth, $newHeight,
            $originalWidth, $originalHeight
        );

        // 保存缩略图
        $success = false;
        switch ($mimeType) {
            case 'image/jpeg':
                $success = imagejpeg($thumbnail, $targetPath, 80);
                break;
            case 'image/png':
                $success = imagepng($thumbnail, $targetPath, 8);
                break;
            case 'image/gif':
                $success = imagegif($thumbnail, $targetPath);
                break;
            case 'image/webp':
                if (function_exists('imagewebp')) {
                    $success = imagewebp($thumbnail, $targetPath, 80);
                }
                break;
        }

        // 清理内存
        imagedestroy($sourceImage);
        imagedestroy($thumbnail);

        if (!$success) {
            throw new Exception("保存缩略图失败: {$targetPath}");
        }
    }

    /**
     * 任务失败时的处理
     */
    public function failed($exception): void
    {
        Log::error("缩略图任务最终失败", [
            'image_file' => $this->imageFile,
            'error' => $exception->getMessage(),
            'attempts' => $this->attempts()
        ]);
    }
}
